package model

import (
	"encoding/json"
	"fmt"
	"github.com/invopop/jsonschema"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/bsontype"
)

type (
	Environment map[string]string
)

const (
	environmentDelimiter = "="
)

func (Environment) JSONSchema() *jsonschema.Schema {
	return &jsonschema.Schema{Ref: fmt.Sprintf(DefinitionsRefTemplate, ListOrDictDefinitionName)}
}

func (d *Environment) UnmarshalJSON(data []byte) error {
	listOrDict := ListOrDict{}
	if err := json.Unmarshal(data, &listOrDict); err != nil {
		return err
	}

	if listOrDict.Dict != nil {
		*d = ConvertDictToDict(listOrDict.Dict)
		return nil
	}

	*d = ConvertListToDict(listOrDict.List, environmentDelimiter)
	return nil
}

func (d *Environment) MarshalJSON() ([]byte, error) {
	var environmentMap map[string]string = *d
	return json.Marshal(environmentMap)
}

func (d *Environment) MarshalBSONValue() (bsontype.Type, []byte, error) {
	var environmentMap map[string]string = *d
	return bson.MarshalValue(environmentMap)
}

func (d *Environment) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
	value := bson.RawValue{Type: t, Value: data}
	listOrDict := ListOrDict{}

	if err := value.Unmarshal(&listOrDict); err != nil {
		return fmt.Errorf("failed to convert environment: %w", err)
	}

	if listOrDict.Dict != nil {
		*d = ConvertDictToDict(listOrDict.Dict)
		return nil
	}

	*d = ConvertListToDict(listOrDict.List, environmentDelimiter)
	return nil
}
